![]() |
PATH![]() |
![]() ![]() |
The SamplePost application calls URLDownload to download information from the InterNIC's whois database. The file SamplePost.h, shown in Listing 2-1 , defines the URL ( kSampleURL ) from which data is to be downloaded and the structure urlDownInfo , which contains all of the information needed to download data from the sample URL.
The SamplePost.h file also includes a declaration of the routine DoSamplePost , which does the actual download, and a system event callback routine, MyURLCallbackProc , which is a place holder for code that handles system events that occur during the download.
Listing 2-1 The SamplePost application's SamplePost.h file
#define kSampleURL "http://www.internic.net/cgi-bin/itts/whois"
typedef struct urlDownInfo *URLDownInfoPtr;
typedef struct urlDownInfo {
URLReference urlRef;
FSSpec * destination;
Handle destinationHandle;
URLOpenFlags openFlags;
URLSystemEventProcPtr eventProc;
void * userContext;
Boolean done;
OSStatus errorCode;
} URLDownloadInfo;
static void DoSamplePost ();
pascal OSStatus MyURLCallbackProc( void*, EventRecord* );
The SamplePost application is multi-threaded, so it calls MaxApplZone and MoreMasters in its main routine, as shown in Listing 2-2 .
Listing 2-2 The SamplePost application's main routine
#include <stdio.h>
#include <Events.h>
#include <Threads.h>
#include <Processes.h>
#include <Files.h>
#include "URLAccess.h"
#include "SamplePost.h"
int main (void)
{
OSStatus err = noErr;
// Call MaxAppleZone() when using the Thread Manager.
MaxApplZone();
for (i = 0; i < 20; i++) {
MoreMasters();
}
In Listing 2-3, the SamplePost application verifies that the URL Access Manager is
available. If the URL Access Manager is available, DoSamplePost, which calls
URLDownload, is called.
Listing 2-3 Verifying the availability of the URL Access Manager
// Make sure the URL Access Manager is available.
if ( URLAccessAvailable()) {
DoSamplePost();
}
else {
// Call error handling routine.
}
}
In Listing 2-4 , the DoSamplePost routine defines a URLDownloadInfo structure named myRef that is uses to store information for calling URLDownload. The DoSamplePost routine calls NewHandle to allocate the memory in which the downloaded information will be stored. Then DoSamplePost creates a URL reference and stores it in myRef.urlRef , which will be used as a parameter when DoSamplePost calls URLDownload .
Listing 2-4 Allocating memory and creating the URL reference
static void DoSamplePost ( void)
{
OSStatus err = noErr;
ThreadID threadID = 0;
URLDownloadInfo myRef;
Handle downloadHandle = nil;
long downloadSize = 0;
printf( "<·>DoSamplePost() Enter\n");
downloadHandle = NewHandle(0);
if ( downloadHandle == nil) {
// Call error handling routine.
}
// Create a URLReference
err = URLNewReference( kSampleURL, &myRef.urlRef );
if ( err != noErr) {
// Call error handling routine.
}
Next, DoSamplePost completes the preparation of the URL reference by calling URLSetProperty to set the value of the URL reference's HTTP Request Method property to POST (a 4-byte string) and the value of the URL reference's HTTP Request Body property to whois_nic=apple.com (a 19-byte string), as shown in Listing 2-5 .
Listing 2-5 Setting URL Access HTTP properties
URLSetProperty(myRef.urlRef, kURLHTTPRequestMethod, "POST", 4);
URLSetProperty(myRef.urlRef, kURLHTTPRequestBody, "whois_nic=apple.com", 19);
Note
When you set the HTTP Request Body property, the URL Access Manager automatically adds the length of the HTTP Request Header to the request, so you do not need to set the HTTP Request Header property explicitly.
Listing 2-6 , DoSamplePost uses the remaining fields of the myRef structure to store values that will be used as parameters for calling URLDownload .
Listing 2-6 Setting the URLDownload parameters
myRef.destination = nil;
myRef.destinationHandle = downloadHandle;
myRef.openFlags = kURLDisplayProgressFlag;
myRef.eventProc = &MyURLCallbackProc;
myRef.userContext = "1";
myRef.errorCode = 0;
Specifically, DoSamplePost does the following in Listing 2-6 :
With the URL reference created, its properties set, and the URLDownload parameters prepared, the DoSamplePost routine is ready to call URLDownload , as shown in Listing 2-7 .
Listing 2-7 Calling the URLDownload function
err = URLDownload( myRef.urlRef,
myRef.destination,
myRef.destinationHandle,
myRef.openFlags,
myRef.eventProc,
myRef.userContext);
myRef.errorCode = err;
if ( myRef.errorCode != noErr) {
// Call error handling routine.
}
else {
// Successful download. Get the size of the downloaded data.
err = URLGetProperty(myRef.urlRef,
kURLResourceSize, &downloadSize, 4);
if ( err != noErr) {
// Call error handling routine.
}
In Listing 2-7 , if the download is successful, the DoSamplePost routine calls URLGetProperty to obtain the size of the downloaded data using the downloadSize parameter, which is 4 bytes long.
In Listing 2-8, DoSamplePost calls SetHandleSize to set the size of downloadHandle to downloadSize + 1 and sets the value of the last byte of downloaded data to NIL . Now that data can be displayed by calling printf . The DoDownload routine concludes by disposing of the URL reference.
Listing 2-8 Displaying the downloaded data
downloadSize = GetHandleSize(downloadHandle);
SetHandleSize(downloadHandle, (downloadSize+1));
(*myRef.destinationHandle)[downloadSize] = nil;
printf( "<·>==================== Downloaded Data ==================\n" );
printf( "%s", *myRef.destinationHandle );
DisposeHandle(downloadHandle);
URLDisposeReference(myref.urlRef);
}
}
Listing 2-9 shows the SamplePost application's system event callback routine.
Listing 2-9 The SamplePost application's system event callback routine
pascal OSStatus MyURLCallbackProc( void *userContext, EventRecord *event )
{
printf( "<·>System callback thread fired! Thread: %u\n", userContext );
return 0;
}
The system event callback routine receives in userContext the value of the userContext parameter that was passed when the application called URLDownload .
Your application's system event callback routine should process the event record passed by the event parameter and return 0.
Note
The only restriction that the URL Access Manager imposes on the functionality of your application's system event callback routine is that it should not call URLDisposeReference .